package client;

import applet.Draft_Applet;
import beans.Draft_Bean;
import java.util.Vector;
import beans.Player_Bean;
import beans.Team_Bean;
import beans.User_Bean;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.Random;

/**********************************************************************
 *
 * Filename: Client_Service.java
 *
 * File Description:
 * Class to handle communications between the applet and the socket connection
 *
 * Author:
 * @author Tim Schmalz
 * Date Created:
 *  Oct 9, 2009
 *
 **********************************************************************/
public class Client_Service
{
	private Client_TCP_Connection socket;
	private boolean isDraft;
        private Vector<Player_Bean> players;
        private Vector<Team_Bean> teams;
        private int teamId;
        private Draft_Applet applet;
        private static Timer timer;
        private static final String NONE = "NONE";

	/**
	 * Creates a new client service object and opens a TCP connection
	 * to the given host and port
	 *
	 * @param host - String holding the host name or IP address
	 * @param port - The port to send messages to
	 * @throws Exception - Catches any exception that was thrown during the
	 *                      connection process
	 */
	public Client_Service(String host, int port, Draft_Applet applet) throws Exception
	{
		socket = new Client_TCP_Connection(host, port);
                this.applet = applet;
	}

	/**
	 * Attempts to login a user
	 *
	 * @param user - User_Bean carrying the users login information
	 * @return boolean dictating if the users was able to login
	 * @throws Exception
	 */
	public boolean login(User_Bean user) throws Exception
	{
		//Send user login information
		socket.serialOut(user);
		//Did they login?
                try
                {
                    user = (User_Bean)socket.serialReadln();
                }
                catch(InterruptedIOException iioe)
                {
                    applet.outputMessage("Login timed out" + '\n' + "Please try again");
                    return false;
                }
		boolean isLoggedIn = user.isLoggedIn();
                System.out.println("Welcome to the live draft "+user.getUserName());
                if(isLoggedIn)
                {
                    try
                    {
                        //Get Players
                        players = (Vector<Player_Bean>)socket.serialReadln();
                        System.out.println("Players Recieved");
                        applet.setPlayerList(players);
                        //Get Teams
                        teams = (Vector<Team_Bean>)socket.serialReadln();
                        System.out.println("Teams Recieved");
                    }
                    catch(InterruptedIOException iioe)
                    {
                        applet.outputMessage("Login timed out" + '\n' + "Please try again");
                        return false;
                    }
                    //Start Waiting on server
                    new WaitForDraftInfo(players,applet,user.getTeamId(),socket, teams, this).start();
                    System.out.println("Draft has begun");
                }
                else
                {
                    applet.outputMessage("Error: " + user.getErrorString());
                }
                return isLoggedIn;
	}

        /**
         * Returns the player's list
         *
         * @return player's list
         */
        public Vector<Player_Bean> getPlayers()
        {
            return players;
        }

        /**
         * Tell the server that player with ID is being drafted
         *
         * @param playerId - Player to be drafted
         */
        public void draftPlayer(int playerId) throws IOException
        {
            //Kill Timer thread
            timer.killTimer();
            //Lock applet
            applet.setAppletUnlock(false);
            //Send draft pick
            socket.serialOut(new Draft_Bean(playerId,-1,-1,-1));
        }

	/**
	 * Private thread that waits for draft message from the server
	 */
	private static class WaitForDraftInfo extends Thread
	{
                private Vector<Player_Bean> players;
                private Draft_Applet applet;
                private int myId;
                private Client_TCP_Connection socket;
                private Vector<Team_Bean> teams;
                private Client_Service clientService;

                /**
                 * Takes drafting thread's variables and builds thread
                 *
                 * @param players - Vector of Players Beans
                 * @param applet - A reference to the GUI so it can be minipulated
                 * @param myId - Calling client's team id
                 * @param socket - Reference to the Client TCP socket
                 * @param teams - Vector of Team Beans
                 * @param clientService - Reference to a client service
                 */
                public WaitForDraftInfo(Vector<Player_Bean> players, Draft_Applet applet, int myId, Client_TCP_Connection socket, Vector<Team_Bean> teams, Client_Service clientService)
                {
                    this.players = players;
                    this.applet = applet;
                    this.myId = myId;
                    this.socket = socket;
                    this.teams = teams;
                    this.clientService = clientService;
                }

        @SuppressWarnings("empty-statement")
                /**
                 * Execute thread's code
                 */
		public void run()
		{
                        boolean isStart = false;
                        String previousPicked = "UNKNOWN";
			while(true)
			{
				try
				{
                                        Draft_Bean draftBean = null;
                                        do
                                        {
                                            try
                                            {
                                                draftBean = (Draft_Bean)socket.serialReadln();
                                                isStart = true;
                                            }
                                            catch(InterruptedIOException iioe)
                                            {
                                                if(isStart)
                                                {
                                                    applet.outputMessage("Draft timed out" + '\n' + "The server will continue to draft for you");
                                                    break;
                                                }
                                            }
                                        }
                                        while(!isStart);
                                        int currentDrafter = draftBean.getTurnId();
                                        int lastPlayerDrafted = draftBean.getPlayerId();
                                        int i;
                                        //Reset the timer
                                        if(lastPlayerDrafted != -1)
                                        {
                                            timer.killTimer();
                                        }
                                        timer = new Timer(applet, clientService, draftBean, myId);
                                        //Set the who's next
                                        String onClock = NONE;
                                        String onDeck = NONE;
                                        String inTheHole = NONE;
                                        //If id returns at -1 it will be ignored in this step causing the name to remain none
                                        for(int j = 0; j < teams.size(); j++)
                                        {
                                            if(draftBean.getTurnId() == teams.get(j).getTeamId())
                                            {
                                                onClock = teams.get(j).getTeamName();
                                            }
                                            if(draftBean.getOnDeckId() == teams.get(j).getTeamId())
                                            {
                                                onDeck = teams.get(j).getTeamName();
                                            }
                                            if(draftBean.getInTheHoleId() == teams.get(j).getTeamId())
                                            {
                                                inTheHole = teams.get(j).getTeamName();
                                            }
                                        }
                                        applet.setOnDeck(onClock,onDeck,inTheHole);
                                        //Exit if draft is over
                                        if (currentDrafter == -1)
                                        {
                                            break;
                                        }
                                        //Start Timer
                                        timer.start();
                                        //Remove Drafted Player from the list
                                        if(lastPlayerDrafted != -1)
                                        {
                                                //Find Player
                                                for(i = 0; i < players.size() && players.get(i).getPlayerId() != lastPlayerDrafted; i++);
                                                if ( i < players.size() )
                                                {
                                                    System.out.println(lastPlayerDrafted);
                                                    applet.setLastPicked(players.get(i).toString());
                                                    applet.outputMessage(previousPicked + " picked " + players.get(i).toString());
                                                    players.remove(i);
                                                }
                                                else
                                                {
                                                    System.err.println("Invalid player: "+lastPlayerDrafted);
                                                }
                                        }
                                        //Set Previous Picked
                                        previousPicked = onClock;
                                        //Check if client is current drafter and update GUI
                                        applet.setPlayerList(players);
                                        if(currentDrafter == myId)
                                        {
                                            applet.setAppletUnlock(true);
                                            applet.outputMessage("-Your Turn-");
                                        }
                                        else
                                        {
                                            applet.setAppletUnlock(false);
                                            //Get who's on the clock
                                            String pickingTeam = "Unknown";
                                            for(int j = 0; j < teams.size(); j++)
                                            {
                                                if(draftBean.getTurnId() == teams.get(j).getTeamId())
                                                {
                                                    pickingTeam = teams.get(j).getTeamName();
                                                    break;
                                                }
                                            }
                                            applet.outputMessage("-" + pickingTeam + "'s Turn-");
                                            socket.serialOut(new Draft_Bean(-1,-1,-1,-1));
                                            
                                        }
				}
				catch(Exception e)
				{
					System.err.println("Error occured in the run method of client service:");
					System.err.println(e.toString());
				}

			}
                        timer.completelyKillTimer();
                        applet.setAppletUnlock(false);
                        socket.close();
                        applet.outputMessage("Draft is Complete");                       
		}
	}

        /**
	 * Private thread that waits for draft message from the server
	 */
	private static class Timer extends Thread
        {
           private Draft_Applet applet;
           private Client_Service clientService;
           private final int START = 90;
           private final int END = 0;
           private boolean userNotPicked = true;
           private static boolean draftEnd = false;
           private Draft_Bean draftBean;
           private int myId;

           /**
            * Build timer
            *
            * @param applet - Reference to GUI
            * @param clientService - Reference to client service
            * @param draftBean - Bean holding draft info
            * @param myId - Calling client's team id
            */
           public Timer(Draft_Applet applet, Client_Service clientService, Draft_Bean draftBean, int myId)
           {
               this.applet = applet;
               this.clientService = clientService;
               this.draftBean = draftBean;
               this.myId = myId;
            }

            /**
             * Building running timer thread
             */
            public void run()
            {
                int i = START;
                try
                {
                    while(i > END && userNotPicked && !draftEnd)
                    {
                        applet.setTimer(i);
                        sleep(1000);
                        i--;
                    }
                    System.out.println(draftEnd);
                    if(userNotPicked && (draftBean.getTurnId() == myId))
                    {
                        applet.setAppletUnlock(false);
                        Random generator = new Random();
                        Player_Bean temp = clientService.getPlayers().get(generator.nextInt(clientService.getPlayers().size()-1));
                        int draftedPlayerId = temp.getPlayerId();
                        clientService.draftPlayer(draftedPlayerId);
                        applet.addPlayerToRoster(temp);
                        System.out.println("User No Pick");
                    }
                    else if(draftEnd)
                    {
                        applet.setTimer(0);
                        System.out.println("DraftEnded");
                    }
                }
                catch (Exception ex)
                {
                    System.err.println("An error occured in the timer thread");
                }
            }

            /**
             * Stop the timer
             */
            public void killTimer()
            {
                userNotPicked = false;
            }

            /**
             * End Timer for Good
             */
            public void completelyKillTimer()
            {
                draftEnd = true;
                userNotPicked = false;
            }
        }
}